package com.example.starter.redis.configure;

import io.lettuce.core.ReadFrom;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author 王令
 * @since 2022-05-06 22:25:56
 */
@EnableConfigurationProperties(RedisExtProperties.class)
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean({RedisTemplate.class})
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 设置键序列化器
        template.setKeySerializer(new StringRedisSerializer());
        // 设置 Hash 键序列化器
        template.setHashKeySerializer(template.getKeySerializer());
        // 设置值序列化器
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        // 设置 Hash 值序列化器
        template.setHashValueSerializer(template.getValueSerializer());

        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(LettuceClientConfigurationBuilderCustomizer.class)
    @ConditionalOnProperty(prefix = "spring.redis", name = "cluster-type", havingValue = "sentinel")
    public LettuceClientConfigurationBuilderCustomizer sentinelClientConfigurationBuilderCustomizer() {
        // MASTER 从主节点读取
        // MASTER_PREFERRED 优先从主节点读取，主节点不可用才读取从节点
        // REPLICA 从从节点读取
        // REPLICA_PREFERRED 优先从从节点读取，从节点都不可用才读取主节点
        return builder -> builder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }

    @Bean
    @ConditionalOnMissingBean(LettuceClientConfigurationBuilderCustomizer.class)
    @ConditionalOnProperty(prefix = "spring.redis", name = "cluster-type", havingValue = "cluster")
    public LettuceClientConfigurationBuilderCustomizer clusterClientConfigurationBuilderCustomizer() {
        // MASTER 从主节点读取
        // MASTER_PREFERRED 优先从主节点读取，主节点不可用才读取从节点
        // REPLICA 从从节点读取
        // REPLICA_PREFERRED 优先从从节点读取，从节点都不可用才读取主节点
        return builder -> builder.readFrom(ReadFrom.REPLICA_PREFERRED);
    }

}
